home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 19.zip / BS1 part 19 / AmigaLibDisk 154.adf / DiskLib / lib.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  13KB  |  499 lines

  1. /***************************************************************
  2. *
  3. *            Lib.c
  4. *
  5. *        Disk Library Documentation System
  6. *            Main Program
  7. *
  8. *    By Wilson Snyder        (c) January 1988
  9. *
  10. ****************************************************************
  11. *
  12. *    NOTICE:
  13. *
  14. *    This program was written as a service to the amiga
  15. *    users.  This program may be used by all parties, including
  16. *    sale (see below) as long as the author's name and address
  17. *    remains intact in the program and documentation.
  18. *    Distribution of this program by parties selling it
  19. *    as part of a commercial for-profit package of over $10
  20. *    must contact the address below before such a package is sold.
  21. *
  22. *    I make no warranties over this program, performance,
  23. *    etc.  And any costs incurred by this program, or its
  24. *    actions are placed on the user.
  25. *
  26. *    PLEASE FORWARD INPROVEMENTS MADE TO THIS PROGRAM TO:
  27. *
  28. *    Wilson Snyder, 15 Davis Parkway, South Burlington, VT 05403
  29. *
  30. ****************************************************************
  31. *
  32. *    AddName and base for Process taken from the TSIZE
  33. *    utility written by the excellent work of the
  34. *    Software Distillery.
  35. *
  36. ****************************************************************/
  37.  
  38. #include "libraries/dosextens.h"
  39. #include "ctype.h"
  40. #include "stdio.h"
  41.  
  42. #define VERSION    "AMIGA-LIB.  Version 1.0.2.  By Wilson Snyder"
  43. #define DESC "$$DES$$"
  44.  
  45. #define PERSUB    8    /* Characters to indent per subdirectory */
  46. #define INFOIND 8    /* Indent for description and filesize */
  47. #define RM    75    /* Right margin */
  48. #define LM    0    /* Left margin */
  49. #define TM    1    /* Top margin */
  50. #define HM    2    /* Header margin (lines after header) */
  51. #define LINES    60    /* Lines per page */
  52.  
  53. BPTR    Lock();        /* Define functions... */
  54. BOOL    Examine();
  55. BOOL    ExNext();
  56.  
  57. char    path [256];        /* Current search path */
  58. char    header [80];        /* Header for top line */
  59. BOOL    prtsize = FALSE;    /* Print the path size information */
  60. BOOL    prtheader = FALSE;    /* Print the header and page breaks */
  61.  
  62. struct Sortem {        /* Linked list for insertion sort of directory names */
  63.     char    FileName[108];    /* Directory name */
  64.     struct Sortem *Next;    /* Pointer to next */
  65.     };
  66.  
  67. /***************************************************************
  68. *            ADDNAME
  69. *
  70. *    Add filename to the end of the current path.
  71. *
  72. *    Routine taken from from TSIZE utility by the Software Distillery.
  73. ***************************************************************/
  74.  
  75. int    AddName(name, len)
  76.     register char *name;
  77.     int len;
  78.     {
  79.     register char *p;    /* current position in path */
  80.     register int i = 0;    /* added length counter */
  81.     char ch;        /* last character of current path */
  82.  
  83.     p = path + len;
  84.  
  85.     /* add a slash between path and name if legal */
  86.     if (len != 0 && (ch = path[len-1]) != '/' && ch != ':') {
  87.         *p++ = '/';
  88.         i++;
  89.         }
  90.  
  91.     /* copy name to end of path (including null terminator) */
  92.     while (*p++ = *name++) i++;
  93.  
  94.     /* return new length of path */
  95.     return (len + i);
  96.     }
  97.  
  98.  
  99. /***************************************************************
  100. *            FILECMP
  101. *    Compare two filenames for sort routine (case insensitive.)
  102. ***************************************************************/
  103.  
  104. int    filecmp(a,b)
  105.     char *a,*b;
  106.     {
  107.     for (;toupper(*a)==toupper(*b);a++,b++)
  108.         if (*a=='\0') return (0);
  109.     return (toupper(*a)-toupper(*b));
  110.     }
  111.  
  112.  
  113. /***************************************************************
  114. *            INDENT
  115. *    Indent a number of spaces.  Outputted to stdout.
  116. ***************************************************************/
  117.  
  118. void    Indent(num)
  119.     int num;
  120.     {
  121.     while (num--)    putchar (' ');
  122.     }
  123.  
  124. /***************************************************************
  125. *            HEADER
  126. *    Print header every so many lines.
  127. ***************************************************************/
  128.  
  129. void    Header(inc)
  130.     int inc;
  131.     {
  132.     static int linecount;        /* Number of lines down */
  133.     static int page;        /* Current page number */
  134.     int t;                /* Temp */
  135.  
  136.     if (inc)
  137.         linecount += inc;
  138.     else    {
  139.         /* 0 increment resets information */
  140.         linecount = 0;
  141.         page = 0;
  142.         }
  143.  
  144.     if (linecount>LINES && prtheader) {
  145.         /* Time to print the header */
  146.         putchar ('\f');
  147.         page++;
  148.         for (t=TM;t;t--)    putchar ('\n');
  149.         printf (header,page);
  150.         for (t=HM;t;t--)    putchar ('\n');
  151.         linecount = TM + HM + 1;
  152.         }
  153.     }
  154.  
  155.  
  156. /***************************************************************
  157. *            ROOT
  158. *    Print information for the page header
  159. ***************************************************************/
  160.  
  161. BOOL    Root()
  162.     {
  163.     struct FileInfoBlock *info;    /* pointer to file info */
  164.     BPTR lock;            /* pointer to file lock */
  165.     int t,loc;            /* temp stuff */
  166.  
  167.     /* allocate an info block (must be longword alligned) */
  168.     if (!(info = (struct FileInfoBlock *)
  169.         AllocMem(sizeof(struct FileInfoBlock), 0))) {
  170.             printf ("Out of memory.\n");
  171.             return (TRUE);
  172.             }
  173.  
  174.     /* try to obtain lock on current file */
  175.     if (!(lock = Lock(path, ACCESS_READ))) {
  176.         printf ("Invalid file or directory, '%s'.\n", path);
  177.         FreeMem(info, sizeof(struct FileInfoBlock));
  178.         return (TRUE);
  179.         }
  180.  
  181.     /* get information on file or directory associated with lock */
  182.     if (!Examine(lock, info)) {
  183.         printf ("Error examining locked file or directory.\n");
  184.         UnLock(lock);
  185.         FreeMem(info, sizeof(struct FileInfoBlock));
  186.         return (TRUE);
  187.         }
  188.  
  189.     /* Make sure user specified a directory, not a file */
  190.     if (info->fib_DirEntryType <= 0) {
  191.         printf ("Must specify a directory, not a file.\n");
  192.         UnLock(lock);
  193.         FreeMem(info, sizeof(struct FileInfoBlock));
  194.         return (TRUE);
  195.         }
  196.  
  197.     /* Build Header line (will be used with printf) */
  198.     loc = 0;
  199.     for (t=LM;t;t--)    header[loc++] = ' ';
  200.     strcpy (&header[loc], "Page %-4d");
  201.     loc += 9;
  202.     for (t=RM-loc-strlen(info->fib_FileName);t;t--)    header[loc++] = ' ';
  203.     strcpy (&header[loc],info->fib_FileName);
  204.     loc += strlen(info->fib_FileName);
  205.     header[loc++] = '\n';
  206.     header[loc] = '\0';
  207.  
  208.     /* Initalize header printer, then force header printing */
  209.     Header (0);
  210.     Header (LINES+2);
  211.  
  212.     UnLock(lock);
  213.     FreeMem(info, sizeof(struct FileInfoBlock));
  214.     return (FALSE);
  215.     }
  216.  
  217.  
  218. /***************************************************************
  219. *            BOTTOM
  220. *    Display size information at bott
  221. om of directory.
  222. ***************************************************************/
  223.  
  224. void    Bottom (depth,size,found)
  225.     int depth;
  226.     long size;
  227.     BOOL found;
  228.     {
  229.     if (prtsize) {
  230.         Indent (depth*PERSUB+INFOIND+LM);
  231.         printf ("Total size %ld bytes.\n", size);
  232.         if (found) printf ("\n");
  233.         Header (2);
  234.         }
  235.     }
  236.  
  237. /***************************************************************
  238. *            DISPLAY
  239. *    Display information from the DESC file in the directory.
  240. ***************************************************************/
  241.  
  242. BOOL    Display (depth,dirname)
  243.     int depth;
  244.     char *dirname;
  245.     {
  246.     FILE *desc;        /* DESCription file info */
  247.     BOOL found;        /* Found a description file */
  248.     int lineloc;        /* Location on the output line */
  249.     int wordlen;        /* Length of word in the buffer */
  250.     char wordstore[RM+10];    /* Storage for current word */
  251.     BOOL Cont;        /* & encountered, ignore return */
  252.     BOOL Long;        /* Long line/word just printed */
  253.     char ch;        /* Character from file */
  254.     int t,lm;        /* temp */
  255.  
  256.     /* Print directory name */
  257.     Header (2);
  258.     Indent (depth*PERSUB+LM);
  259.     printf ("%s\n", dirname);
  260.  
  261.     /* Add DESC filename to path, attempt to open the file */
  262.     t = strlen(path);
  263.     AddName (DESC,t);
  264.     found = ((desc=fopen(path,"r"))!=0);
  265.  
  266.     /* If found, justify the file on the way out */
  267.     if (found) {
  268.         lm = depth*PERSUB+INFOIND+LM;
  269.         lineloc = lm;
  270.         Indent (lm);
  271.         wordlen = 0;
  272.         Cont = FALSE;
  273.         Long = FALSE;
  274.         /* Process one character at a time */
  275.         while ((ch=getc(desc))!=EOF) {
  276.             /* Ignore return if proceded by a & */
  277.             if ((ch=='\n') && Cont) {
  278.                 Cont = FALSE;
  279.                 continue;
  280.                 }
  281.             if (Cont) {    /* & not proceded by a return */
  282.                 wordstore[wordlen++] = '&';
  283.                 Cont = FALSE;
  284.                 }
  285.             /* Dump out the current word */
  286.             if (ch==' ' || ch=='\n') {
  287.                 wordstore[wordlen] = '\0';
  288.                 printf ("%s ",wordstore);
  289.                 lineloc += wordlen + 1;
  290.                 wordlen = 0;
  291.                 if (Long || ch=='\n') {
  292.                     putchar ('\n');
  293.                     Header(1);
  294.                     Indent (lm);
  295.                     lineloc = lm;
  296.                     Long = FALSE;
  297.                     }
  298.                 continue;
  299.                 }
  300.             /* Force return if line goes over right margin */
  301.             if (((wordlen+lineloc)>RM) || (wordlen>(RM-lm))) {
  302.                 if (wordlen>(RM-lm)) {
  303.                     wordstore[wordlen] = '\0';
  304.                     printf ("%s",wordstore);
  305.                     wordlen = 0;
  306.                     Long = TRUE;
  307.                     }
  308.                 putchar ('\n');
  309.                 Header(1);
  310.                 Indent (lm);
  311.                 lineloc = lm;
  312.                 }
  313.             /* Check for continuation character */
  314.             if (ch=='&')    Cont = TRUE;
  315.             else    wordstore[wordlen++] = ch;
  316.             }
  317.         fclose (desc);
  318.         /* Dump out any remaining word in the buffer */
  319.         if (wordlen) {
  320.             wordstore[wordlen] = '\0';
  321.             puts (wordstore);
  322.             putchar ('\n');
  323.             Header (1);
  324.             lineloc=0;
  325.             }
  326.         if (lineloc>lm)    putchar('\n');
  327.         putchar('\n');
  328.         }
  329.  
  330.     /* Restore path, return status if file was found */
  331.     path[t] = '\0';
  332.     return (found);
  333.     }
  334.  
  335.  
  336. /*************************************************************
  337. *            PROCESS
  338. *
  339. *    Find the size of a directory tree by adding the sizes
  340. *    of all files in the directory and all of its subdirectories.
  341. *
  342. *    General directory searching concept taken from TSIZE
  343. *    utility by the Software Distillery.
  344. ************************************************************/
  345.  
  346. long    Process(len,depth)
  347.     int len;    /* Length of path name */
  348.     int depth;    /* Number of directories down */
  349.     {
  350.     struct FileInfoBlock *info = NULL;    /* pointer to file info */
  351.     struct Sortem *sort_top = NULL;        /* top of sort list */
  352.     struct Sortem *sort_cur = NULL;        /* current sort list loc */
  353.     struct Sortem *sort_tmp = NULL;        /* current sort temp loc */
  354.     struct Sortem *sort_last= NULL;        /* last sort temp loc */
  355.     long size = 0;                /* running total of file size */
  356.     BPTR lock;                /* pointer to file lock */
  357.     BOOL found;                /* found DESC file */
  358.  
  359.     /* Try to obtain lock on current directory */
  360.     if (!(lock = Lock(path, ACCESS_READ))) {
  361.         printf ("Invalid directory, '%s'.\n", path);
  362.         goto EXIT;
  363.         }
  364.  
  365.     /* Allocate an info block (must be longword alligned) */
  366.     if (!(info = (struct FileInfoBlock *)
  367.         AllocMem(sizeof(struct FileInfoBlock), 0))) {
  368.             printf ("Out of memory.\n");
  369.             goto EXIT;
  370.             }
  371.  
  372.     /* Get information on file or directory associated with lock */
  373.     if (!Examine(lock, info)) {
  374.         printf ("Error examining locked directory.\n");
  375.         goto EXIT;
  376.         }
  377.  
  378.     /* This should not happen, but... */
  379.     if (info->fib_DirEntryType <= 0)  {
  380.         printf ("Locked a file, not directory.\n");
  381.         goto EXIT;
  382.         }
  383.  
  384.     /* Display top of directory header */
  385.     found = Display (depth,info->fib_FileName);
  386.  
  387.     /* Read this directory */
  388.     while (ExNext(lock, info)) {
  389.         /* This is a directory */
  390.         if (info->fib_DirEntryType > 0)    {
  391.             /* sub-directory, allocate sortem node */
  392.             if (!(sort_cur = (struct Sortem *)
  393.                     AllocMem(sizeof(struct Sortem), 0))) {
  394.                 printf ("Out of memory.\n");
  395.                 break;
  396.                 }
  397.             strcpy(sort_cur->FileName,info->fib_FileName);
  398.             sort_cur->Next = NULL;
  399.  
  400.             /* Alphabetical insertion sort */
  401.             /* Find insertion location for new node */
  402.             for (sort_tmp = sort_top; sort_tmp; 
  403.                 sort_tmp = sort_tmp->Next) {
  404.                 if (filecmp(sort_tmp->FileName,info->fib_FileName)>0)
  405.                     break;
  406.                 sort_last = sort_tmp;
  407.                 }
  408.  
  409.             /* Insert the node */
  410.             if (sort_tmp==sort_top) {
  411.                 sort_cur->Next = sort_top;
  412.                 sort_top = sort_cur;
  413.                 }
  414.             else    if (!sort_tmp) {
  415.                 sort_cur->Next = NULL;
  416.                 sort_last->Next = sort_cur;
  417.                 }
  418.                 else {
  419.                     sort_cur->Next = sort_last->Next;
  420.                     sort_last->Next = sort_cur;
  421.                     }
  422.             sort_cur = NULL;
  423.             }
  424.         else     /* found a file, just add size */
  425.             size += info->fib_Size;
  426.         }
  427.  
  428.     /* Transverse sorted list, process then deallocate the node */
  429.     for (sort_tmp = sort_top; sort_tmp; sort_tmp = sort_last) {
  430.         size += Process(AddName(sort_tmp->FileName, len),depth+1);
  431.         sort_last = sort_tmp->Next;
  432.         FreeMem(sort_tmp, sizeof(struct Sortem));
  433.         }
  434.  
  435.     /* Repair path */
  436.     path[len] = '\0';
  437.  
  438.     /* Print bottom of directory information */
  439.     Bottom (depth, size, found);
  440.  
  441.     EXIT:
  442.     if (info) FreeMem(info, sizeof(struct FileInfoBlock));
  443.     if (lock) UnLock(lock);
  444.     return(size);
  445.     }
  446.  
  447. /***************************************************************
  448. *            MAIN
  449. ***************************************************************/
  450.  
  451. main(argc, argv)
  452.     int argc;
  453.     char *argv[];
  454.     {
  455.     int len;    /* Length of file name given on command line */
  456.     int t;        /* Temp variable */
  457.  
  458.     /* Help information */
  459.     if (argv[1][0]=='?') {
  460.         printf ("%s\nUseage: %s [Read-Path] [-size]\n",
  461.             VERSION, argv[0]);
  462.         exit (0);
  463.         }
  464.  
  465.     /* parse command line (len used as temp param counter) */
  466.     for (len=1;len<argc;len++)
  467.         if (argv[len][0]=='-') {    /* switch */
  468.             switch (toupper(argv[len][1])) {
  469.                 case 'S':    /* Size Flag */
  470.                     prtsize = TRUE;
  471.                     break;
  472.                 case 'H':    /* Header Flag */
  473.                     prtheader = TRUE;
  474.                     break;
  475.                 /* ADD OTHER SWITCHES HERE */
  476.                 default:
  477.                     printf ("Bad Switch.\n");
  478.                 }
  479.  
  480.             /* Drop this argument */
  481.             argc--;
  482.             for (t=len;t<argc;t++)    argv[t] = argv[t+1];
  483.             }
  484.  
  485.     /* Process pathname */
  486.     if (argc>1)
  487.         len = AddName(argv[1], 0);
  488.     else    len = AddName(":", 0);
  489.  
  490.     /* Check root info, exit if invalid */
  491.     if (Root()) return(20);
  492.  
  493.     /* Process root directory */
  494.     (void)Process(len,0);
  495.  
  496.     EXIT:
  497.     return(0);
  498.     }
  499.